<template>
	<el-dialog v-model="visible" title="轨迹地图" width="80%" top="5vh" destroy-on-close>
		<!-- 顶部信息栏 -->
		<div class="map-header">
			<!-- 左侧信息区 -->
			<div class="info-container">
				<div class="info-item">
					<span class="label">CMCC里程：</span>
					<span class="value">{{ mileage }} 公里</span>
				</div>
				<div class="info-item" v-if="province || city || district">
					<span class="label">省-市-县：</span>
					<span class="value">{{ province }} - {{ city }} - {{ district }}</span>
				</div>
			</div>

			<!-- 右侧按钮区 -->
			<div class="button-container">
				<el-button
					@click="toggleMapType"
					size="small"
					class="map-toggle-btn"
					:icon="showImagery ? 'MapLocation' : 'Picture'"
				>
					{{ showImagery ? '矢量地图' : '影像地图' }}
				</el-button>
			</div>
		</div>

		<!-- 地图容器 -->
		<div id="mapContainer" style="width: 100%; height: 70vh;"></div>

		<!-- 底部按钮 -->
		<template #footer>
			<el-button @click="visible = false">关闭</el-button>
		</template>
	</el-dialog>
</template>

<script setup lang="ts">
import { ref, nextTick } from 'vue'

// OpenLayers 导入
import 'ol/ol.css';
import Map from 'ol/Map'
import View from 'ol/View'
import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import Feature from 'ol/Feature'
import Point from 'ol/geom/Point'
import LineString from 'ol/geom/LineString'
import { Icon, Style, Circle as CircleStyle, Fill, Stroke } from 'ol/style'
import { ScaleLine } from 'ol/control';
import Overlay from 'ol/Overlay'
import { tiandituLayer, annotationLayer, tiandituImgLayer, imgAnnotationLayer } from '/@/api/map/map';

// 图标资源
import origin from '/@/assets/images/origin.png'
import terminal from '/@/assets/images/terminal.png'
import arrow from '/@/assets/images/arrow.png';

// 弹窗控制
const visible = ref(false)
const mileage = ref(0)
const province = ref('')
const city = ref('')
const district = ref('')

// 地图实例和图层
let map: Map | null = null
let vectorSource: VectorSource | null = null
let popupOverlay: Overlay | null = null

// 动态加载 OpenLayers CSS（防止未加载）
const loadOpenLayersCSS = () => {
	const id = 'ol-css'
	if (document.getElementById(id)) return
	const link = document.createElement('link')
	link.id = id
	link.rel = 'stylesheet'
	link.href = 'https://cdn.jsdelivr.net/npm/ol@v7.4.0/ol.css'
	document.head.appendChild(link)
}

// 在setup部分添加响应式变量
const showImagery = ref(false)

// 添加切换地图类型的函数
const toggleMapType = () => {
	if (!map) return

	showImagery.value = !showImagery.value

	// 获取图层
	const layers = map.getLayers()

	// 矢量图和标注
	layers.item(0).setVisible(!showImagery.value) // 矢量底图
	layers.item(1).setVisible(!showImagery.value) // 矢量标注

	// 影像图和影像标注
	layers.item(2).setVisible(showImagery.value) // 影像底图
	layers.item(3).setVisible(showImagery.value) // 影像标注
}

// 初始化地图
const initMap = async () => {
	await nextTick()
	loadOpenLayersCSS()

	// 清除旧地图
	if (map) {
		map.setTarget(undefined)
	}

	// 创建矢量源
	vectorSource = new VectorSource()

	// 矢量图层
	const vectorLayer = new VectorLayer({
		source: vectorSource,
	})

	// 创建地图
	map = new Map({
		target: 'mapContainer',
		layers: [
			tiandituLayer,
			annotationLayer,
			tiandituImgLayer,
			imgAnnotationLayer,
			vectorLayer
		],
		view: new View({
			projection: 'EPSG:4326',
			zoom: 8,
			center: [105, 38], // 中国中心
		}),
	})

	// 创建并添加比例尺控件
	const scaleLineControl = new ScaleLine({
		units: 'metric', // 设置为公制单位
	});
	map.addControl(scaleLineControl);

	// === 创建弹窗 DOM 元素 ===
	const popupElement = document.createElement('div');
	popupElement.className = 'ol-popup';
	popupElement.id = 'popupId'; // 添加一个 ID 以便于查找
	popupElement.style.cssText = `
  position: absolute;
  background: #444;
  box-shadow: 0 2px 10px rgba(0,0,0,0.2);
  border-radius: 6px;
  padding: 10px;
  width: 170px;
  font-size: 12px;
  color: white;
  z-index: 9999;
  pointer-events: auto;
  transform: translate(-50%, calc(-100% - 12px)); /* 让弹窗顶部居中对准点 */
`;

// 创建小三角（指向下方）
	const triangleDiv = document.createElement('div');
	triangleDiv.className = 'popup-triangle';
	triangleDiv.style.cssText = `
  position: absolute;
  bottom: -10px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-top: 10px solid #444;        /* 与背景色一致 */
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  pointer-events: none;
`;

// 将小三角添加到弹窗元素中
	popupElement.appendChild(triangleDiv);

// 将弹窗添加到 body
	document.body.appendChild(popupElement);

// 创建 Overlay
	let popupOverlay = new Overlay({
		element: popupElement,
		positioning: 'bottom-center',
		// offset: [0, -40],
		autoPan: true,
		autoPanAnimation: { duration: 200 },
	});
	map.addOverlay(popupOverlay);

// === 地图点击事件：显示或隐藏弹窗 ===
	map.on('click', (event) => {
		// 检查是否点击到轨迹点
		const feature = map.forEachFeatureAtPixel(event.pixel, (feat) => feat);

		if (feature && feature.get('trajectoryItem')) {
			const item = feature.get('trajectoryItem');
			const coordinate = ([item.lng, item.lat]); // 使用  转换坐标

			// 判断是起点、终点还是中间点
			const isStartOrEnd = feature.get('isStart') || feature.get('isEnd');

			// 根据是否为起点/终点，设置不同的 offset
			popupOverlay.setOffset([0, isStartOrEnd ? -35 : 0]);

			// 构建内容（仅经度、纬度、海拔）
			const content = `
      <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;">
        <div style="padding: 8px; border-bottom: 1px solid #eee; font-weight: 600; background: #444; border-radius: 4px 4px 0 0;">
          轨迹点详情
        </div>
        <div style="padding: 12px 16px; line-height: 28px; font-size: 14px; color: white;">
          <div><strong>经度：</strong>${Number(item.lng).toFixed(6)}</div>
          <div><strong>纬度：</strong>${Number(item.lat).toFixed(6)}</div>
          <div><strong>海拔：</strong>${Number(item.alt).toFixed(2)} 米</div>
          <div><strong>卫星：</strong>${Number(item.satelliteCount)}</div>
        </div>
      </div>
    `;

			// 获取弹窗 DOM 元素
			const popupElement = popupOverlay.getElement();
			if (!popupElement) return;

			// 清除旧内容，插入新内容
			const contentDiv = document.createElement('div');
			contentDiv.className = 'ol-popup-content';
			contentDiv.innerHTML = content;
			// 先移除旧内容
			const oldContent = popupElement.querySelector('.ol-popup-content');
			if (oldContent) oldContent.remove();
			popupElement.appendChild(contentDiv);

			// 显示弹窗
			popupOverlay.setPosition(coordinate);
		} else {
			// 点击空白处，关闭弹窗
			popupOverlay.setPosition(undefined);
		}
	});
}

// 打开对话框并渲染轨迹
const openDialog = async (
	trajectoryData: any[],
	mileageData: number,
	addressInfo?: { province: string; city: string; district: string }
) => {
	visible.value = true
	mileage.value = mileageData || 0
	province.value = addressInfo.province;
	city.value = addressInfo.city;
	district.value = addressInfo.district;

	await nextTick()
	await initMap()

	if (!map || !vectorSource) return

	// 清空之前的数据
	vectorSource.clear()

	// 转换轨迹点为 OpenLayers 格式
	const coordinates = trajectoryData.map((item) => [item.lng, item.lat])

	// 绘制轨迹线
	const lineFeature = new Feature({
		geometry: new LineString(coordinates),
	})
	lineFeature.setStyle(
		new Style({
			stroke: new Stroke({
				color: '#0059ff',
				width: 1.5,
				lineDash: [0],
			}),
		})
	)
	vectorSource.addFeature(lineFeature)

	function createArrowedLineStyle(coordinates, arrowSrc) {
		const features = []; // 返回 Feature 数组

		for (let i = 0; i < coordinates.length - 1; i++) {
			const start = coordinates[i];
			const end = coordinates[i + 1];

			// 计算旋转角度
			const dx = end[0] - start[0];
			const dy = end[1] - start[1];
			let tempRotation = Math.atan2(dy, dx); // 两点间夹角弧度
			let rotation;
			let PI = Math.PI;

			// 根据箭头图标的方向重新计算旋转弧度，此处为上箭头
			if (tempRotation < PI / 2) {
				rotation = PI / 2 - tempRotation;
			} else if (tempRotation > PI / 2) {
				rotation = -(tempRotation - PI / 2);
			} else {
				rotation = 0;
			}

			// 创建箭头 Feature
			const arrowFeature = new Feature({
				geometry: new Point(end), // 箭头放置在终点位置
			});

			// 设置样式，应用计算出的角度
			arrowFeature.setStyle(
				new Style({
					image: new Icon({
						src: arrowSrc,
						anchor: [0.5, 0], // 锚点在图像底部中心
						rotateWithView: true, // 图标随视图旋转
						rotation: rotation, // 应用计算出的旋转
						scale: 0.8,
					}),
				})
			);

			features.push(arrowFeature); // 添加到features数组
		}

		return features; // 返回生成的features数组
	}

	// 直接添加箭头 Feature
	const arrowFeatures = createArrowedLineStyle(coordinates, arrow);
	vectorSource.addFeatures(arrowFeatures);

	// 起点
	if (coordinates[0]) {
		const startFeature = new Feature({
			geometry: new Point(coordinates[0]),
		})
		startFeature.setStyle(
			new Style({
				image: new Icon({
					src: origin,
					scale: 1,
					anchor: [0.5, 1],
					anchorXUnits: 'fraction',
					anchorYUnits: 'fraction',
				}),
				zIndex: 1000
			})
		)
		startFeature.set('trajectoryItem', trajectoryData[0])
		startFeature.set('isStart', true)
		vectorSource.addFeature(startFeature)
	}

	// 终点
	const lastIdx = coordinates.length - 1
	if (coordinates[lastIdx]) {
		const endFeature = new Feature({
			geometry: new Point(coordinates[lastIdx]),
		})
		endFeature.setStyle(
			new Style({
				image: new Icon({
					src: terminal,
					scale: 1,
					anchor: [0.5, 1],
					anchorXUnits: 'fraction',
					anchorYUnits: 'fraction',
				}),
				zIndex: 1000
			})
		)
		endFeature.set('trajectoryItem', trajectoryData[lastIdx])
		endFeature.set('isEnd', true)
		vectorSource.addFeature(endFeature)
	}

	// 添加中间点（小蓝点）
	for (let i = 1; i < coordinates.length - 1; i++) {
		const pointFeature = new Feature({
			geometry: new Point(coordinates[i]),
		})
		pointFeature.setStyle(
			new Style({
				image: new CircleStyle({
					radius: 2,
					fill: new Fill({ color: '#0059ff' }),
				}),
			})
		)
		pointFeature.set('trajectoryItem', trajectoryData[i])
		vectorSource.addFeature(pointFeature)
	}

	// 调整视图到轨迹范围
	map.getView().fit(vectorSource.getExtent(), {
		padding: [50, 50, 50, 50],
		maxZoom: 18,
	})
}
defineExpose({ openDialog })
</script>

<style scoped>
.map-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 10px;
	padding: 0 10px;
}

.info-container {
	display: flex;
	gap: 20px;
	align-items: center;
}

.button-container {
	display: flex;
	gap: 10px;
}

.info-item {
	display: flex;
	align-items: center;
	font-size: 14px;
}

.label {
	color: #666;
	margin-right: 5px;
}

.value {
	font-weight: 500;
}

.map-toggle-btn {
	margin-left: auto;
	background-color: #f5f7fa;
	border-color: #e4e7ed;
}

.map-toggle-btn:hover {
	background-color: #ecf5ff;
	border-color: #d9ecff;
}
</style>
